/**
 * Created with IntelliJ IDEA.
 * Description: 双向链表
 * User: mac
 * Date: 2022-09-03
 * Time: 9:21
 */

class ListNode{
    public int val;
    public ListNode next;
    public ListNode prev;

    public ListNode(int val){
        this.val = val;
    }
}
public class DoubleLinkedList {
    public ListNode head;//指向双向链表的头结点
    public ListNode last;//指向双向链表的尾结点

    //打印
    public void display() {
        if (this.head == null){
            return;
        }
        ListNode cur = this.head;
        while (cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    //得到单链表长度
    public int size() {
        if (this.head == null){
            return 0;
        }
        ListNode cur = this.head;
        int count = 0;
        while (cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }

    //查找是否包含关键字key节点是否在单链表中
    public boolean contains(int key){
        if (this.head == null){
            return false;
        }
        ListNode cur = this.head;
        while (cur != null){
            if (cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return  false;
    }

    //头插法
    public void addFirst(int data){
        ListNode node = new ListNode(data);

        if (this.head == null){
            this.head = node;
            this.last = node;
        } else {
            node.next = this.head;
            this.head.prev = node;
            this.head = node;
        }
    }

    //尾插法
    public void addLast(int data){
        ListNode node = new ListNode(data);

        if (this.head == null){
            this.head = node;
            this.last = node;
        } else{
            this.last.next = node;
            node.prev = this.last;
            this.last = node;
        }
    }

    //删除第一次关键字为K的节点
    public void remove(int k){
        if (this.head == null){
            System.out.println("链表为空");
            return;
        }

        ListNode cur = this.head;
        while (cur != null){
            if (cur.val == k){
                if (cur == this.head){
                    head = head.next;
                    if (head == null){
                        last = null;
                        return;//坑
                    }
                    head.prev = null;
                    return;
                }
                if (cur.next == null){
                    last = last.prev;
                    last.next = null;
                    return;
                }
                cur.prev.next = cur.next;
                cur.next.prev = cur.prev;
                return;
            }
            cur = cur.next;//经常搞忘
        }
        if (cur == null){
            System.out.println("未找到关键字为k的节点");
        }
    }

    public ListNode search(int index){
        ListNode cur = this.head;

        while (index != 0){
            cur = cur.next;
            index--;
        }
        return cur;
    }
    //任意位置插入，第一个数据节点为0号下标
    public void addIndex(int index,int data){
        if (index < 0 || index > size()){
            System.out.println("插入位置不合法！");
            return;
        }
        ListNode node = new ListNode(data);
        /*if (this.head == null){
            this.head = node;
            this.last = node;
            return;
        }*///挫狗
        if (index == 0){
            addFirst(data);
            return;
        }
        if (index == size()){
            addLast(data);
            return;
        }
        ListNode cur = search(index);
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;
    }

    //删除所有值为key的节点
    public void removeAllKey(int k){
        if (this.head == null){
            System.out.println("链表为空");
            return;
        }

        ListNode cur = this.head;
        while (cur != null){
            if (cur.val == k){
                if (cur == this.head){
                    head = head.next;
                    if (head == null){
                        last = null;
                        return;//坑
                    }
                    head.prev = null;
                } else if (cur.next == null){
                    last = last.prev;
                    last.next = null;
                } else {
                    cur.prev.next = cur.next;
                    cur.next.prev = cur.prev;
                }
            }
            cur = cur.next;//经常搞忘
        }
        if (cur == null){
            System.out.println("未找到关键字为k的节点");
        }
    }

    //清空链表
    public void claer(){
        while (head != null){
            ListNode curNext = head.next;
            head.next = null;
            head.prev = null;
            head = curNext;
        }
        last = null;
    }

    //当面试官文*****和*****区别的时候，一定记住，从共同点出发
    //这两个数据结构的共同点无非就是对数据的组织方式和描述方法不一样
    //组织：
    //顺序表底层是一个十组，他是一个逻辑上和物理上都是连续的
    //链表是一个由若干节点组成的一个数据结构，逻辑上是连续的，但在物理上是不连续的
    //操作：
    //1.顺序表适合查找相关的操作，因为可以使用下标，直接获取到某个位置的元素
    //2.链表适合于频繁的插入删除操作，此时你不需要像顺序表一样，需要移动元素。链表的插入
    //只需要修改指向即可
    //3.顺序表还有不好的地方，就是你需要看满不满，满了要扩容，扩容之后，不一定能放完
    //所以空间利用率不高
}
